-- 游戏服的总入口
-- 如果玩家在某张桌子上，则请求转发给桌子 service来执行

local filename = "router.lua"

local skynet = require "skynet"
local cluster = require "skynet.cluster"
require "skynet.manager"

local filelog = require "filelog"
local routerbase = require "routerbase"
local List = require "list"

local json = require "cjson"
json.encode_sparse_array(true, 1, 1)

require "imenum"

local Router = routerbase:new({
	idle_talk_mng = nil,	-- 空闲聊天对象生成器
	-- 这里容易混淆，有一个是桌子table的自然编号 1，2，3，4，5，变量名为index
	-- 一个是桌子的随机码（编码），变量名为code
	index_to_talk = {},	-- 通过桌子的内部序列号（index）来找到桌子，可以用在节点重启后重构桌子(tablemap 是个整体)
							-- {index=table_service}
	talk_index = 1,	    -- 序列号，自增调用，既方便管理，也是桌子的主索引
	role_map = {}, 			-- 主键就是rid
    game_talk_list = {
        idle_talk = List:new(),   -- 空位桌子列表,内含3个list，对应3种场次,每个list元素为： talk_index
    },    
})

function Router:init()
	self:add_func("nodemsg/noderequest")
    self:add_func("nodemsg/nodecmd")
end

-----------------

--
-- 保存角色到桌子的映射关系
-- 通知gate玩家进桌
--
function Router:forward(rid, talkservice, talk_index)
	if self.role_map[rid] == nil then
		self.role_map[rid] = { talk_service = talkservice, talk_index = talk_index }
		-- status = skynet.pcall(cluster.send,"gatenode", ".router", "role_enter_table", rid, skynet.getenv("nodename"), talk_index)
  --       if not status then
  --           filelog.sys_error("call gatenode error!")
  --       else
  --           filelog.print(rid ,"enter table")
  --       end
	end
end

--
-- 取消角色到桌子的映射关系
-- 通知gate玩家离桌
--
function Router:unforward(rid, talk_index, coin)
	if self.role_map[rid] then
        if talk_index ~= self.role_map[rid].talk_index then
            talk_index = self.role_map[rid].talk_index or talk_index
            filelog.sys_error("-----------error table_index---------", rid, talk_index)
        end
		self.role_map[rid] = nil
        -- if talk_index and self.index_to_table[talk_index] then
        --     local level = self.index_to_table[talk_index].level_type
        --     self.diff_level_players[level] = (self.diff_level_players[level] or 0) - 1
        -- end
    end
    --local status, result = skynet.call(".agentmgr", "lua", "cmd", "clear_tableaddress_by_rid", rid)
	--local status = skynet.pcall(cluster.send,"gatenode", ".router", "role_leave_table", rid, skynet.getenv("nodename"), talk_index, coin)
    -- if not status then
    --     filelog.sys_error("call gatenode error!")
    -- else
    --     filelog.print(rid ,"leave table")
    -- end
end

--
-- 获得一个uuid
--
function Router:get_tradeid()
    return skynet.call(".nodeuuid", "lua", "getuuid")
end

--
--获取玩家数据
--
function Router:get_role_data(rid)
    return self.role_map[rid]
end

-------------------
-- 测试接口

--
--查看游戏状态
--
local function watch()
    while true do
        skynet.sleep(53 *100)
        skynet.send(".router", "lua","cmd", "getgamestate")
    end
end

--
--检测游戏状态
--
local function check()
    while true do
        skynet.sleep(20 * 100)
        skynet.send(".router", "lua","cmd", "checkgamestate")
    end
end


local talkcmdstrings = {
    "entertalk",
    "opensession",
    "sendmessage",
    "reentertalk",
    "deletemessage",
    "cleanmessages",
    "getmessage",
    "getalltalkrids",
    "gmhttprequest",
}

local function cmdtalkcmds(cmd)
    local is_talkcmd = false
    for index, talkcmd in pairs(talkcmdstrings) do
        if talkcmd == cmd then
            is_talkcmd = true
            break
        end
    end
    return is_talkcmd
end
-------------------
--服务入口

skynet.start(function()
    skynet.dispatch("lua", 
        function (session, source, command, rid, arg1, ...)
	        local status = true
            local result = nil
            if Router[command] then
                local func = Router[command]
                result = func(Router,rid,arg1,...)
                return skynet.retpack(result)
            end
	        if rid and Router.role_map[rid] and Router.role_map[rid].talk_service then
			    status, result = skynet.pcall(skynet.call, Router.role_map[rid].talk_service, "lua", "request", command, rid, arg1, ...)
		        if not status then
                    filelog.sys_error("call table service failed!", rid)
                    Router:unforward(rid, Router.role_map[rid].talk_index, 0)
			        result = {retcode = EErrCode.ERR_SYSTEM_ERROR, retstr = "call_table_service_failed"}
		        end
	        else
		        local f = Router.CMD[command]
		        if f == nil then
                    local args = ...
                    local retable = {
                        retstr = "role_not_in talk",
                        command = command,
                        request = args or {},
                    }
                    result = {retcode = EErrCode.ERR_NOT_IN_TALK, retstr = json.encode(retable)}
                    filelog.sys_error("line170" .. filename.." CMD[command] is nil : ", rid, command, result, args)
                    --[[
                    local is_talkcmd = cmdtalkcmds(cmd)
                    if is_talkcmd == true then
                        status, result = skynet.pcall(Router.CMD["auto_entertalk"], rid, arg1, ...)
                        if status == true and result and result.retcode == nil then
                            if rid and Router.role_map[rid] and Router.role_map[rid].talk_service then
                                status, result = skynet.pcall(skynet.call, Router.role_map[rid].talk_service, "lua", "request", command, rid, arg1, ...)
                                if not status then
                                    filelog.sys_error("call table service failed!", rid)
                                    Router:unforward(rid, Router.role_map[rid].talk_index, 0)
                                    result = {retcode = EErrCode.ERR_SYSTEM_ERROR, retstr = "call_table_service_failed"}
                                end
                            end
                        else
                            filelog.sys_error("line174" .. filename.." CMD[command] is nil : ", rid, command)
                            result = {retcode = EErrCode.ERR_NOT_IN_TALK, retstr = "role_not_in talk"}
                        end
                    end
                    --]]
		        else
			        if type(f) == "function" then
                        if  rid == nil then
                            status, result = skynet.pcall(f, arg1, ... )
                        elseif rid == 0 then
                            result = {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "无效的用户id"}
                        else
					        status, result = skynet.pcall(f, rid, arg1, ... )
                        end
				        if not status then
					        filelog.sys_error(filename.." CMD[command] skynet.pcall failed : ", command, rid, result, arg1, ...)
				        end
			        else
				        filelog.sys_error("role not in talk",command)
				        result = {retcode = EErrCode.ERR_NOT_IN_TALK, retstr = "role_not_in talk"}
			        end
		        end
	        end
	        skynet.retpack(result)
    end)
    Router:init()

    --测试
    skynet.fork(watch)
    skynet.fork(check)
end)
